<?php
/**
 * +----------------------------------------------------------------------+
 * php23种设计模式实现-备忘录模式
 * Author：微信公众号：yuantanphp
 * 获取更多资源，技术答疑，项目合作请关注微信公众号：yuantanphp
 * +----------------------------------------------------------------------+
 */
namespace Memorandum;
//备忘录类
class Memento{
    public $_number;    //备忘录编号
    public $_name;       //员工姓名
    public $_sumLateMinute;   //迟到累计

    function __construct($number,$name,$sumLateMinute){
        $this->_number = $number;
        $this->_name = $name;
        $this->_sumLateMinute = $sumLateMinute;
    }
}
//备忘录管理器
class Originator{
    //备忘录列表
    public static $mementos = array();
    //单例
    private static $instance = null;
    //单例模式确保只有一个管理器
    private function __construct(){}
    //单例模式防止外部克隆
    private function __clone(){}
    //返回单例对象
    static function getInstance(){
        if(!(self::$instance instanceOf self)){
             self::$instance = new self();
        }
        return self::$instance;
    }
    //存备忘录
    function addMemento($id,Memento $memento){
        self::$mementos[$id] = $memento;
    }
    //取备忘录
    function getMemento($id){
        return self::$mementos[$id];
    }
}
//员工考勤
class Staff{
    private static $i = 0;  //静态变量累加用于给$id赋值
    public $_number; //每个对象独一无二，用于保存状态备忘录到管理器
    private $_name; //姓名
    private $_sumLateMinute;  //迟到分钟数
    private $_maxMinute;

    function __construct($name){
        $this->_name = $name;
        $this->_number = self::$i;
        self::$i++;
    }
    //初始化
    function init(){
        $this->_maxMinute = 300;
        $this->_sumLateMinute = 0;
    }

    //登记迟到行为
    function regLate($minute){
        $this->_sumLateMinute +=$minute;
    }
   
    //显示现有状态
    function displayState(){
        echo "姓  名：".$this->name."<br/>";
        echo "已迟到：".$this->_sumLateMinute." 分钟<br/>";
        if($this->_sumLateMinute <= $this->_maxMinute){
            $lates = $this->_maxMinute - $this->_sumLateMinute;
            echo "剩余可迟到 ".$lates." 分钟 超出部分将处以罚款<br />";
        }else{
            echo "已超出，将被处以罚款 <br />";
        }
    }

    //保存状态到一个备忘录中，该备忘录将被放置到管理器中
    function saveState(){
        $originator = Originator::getInstance();
        $originator->addMemento($this->id,new Memento($this->_number,$this->_name,$this->_sumLateMinute));
    }
    //恢复备忘录
    function resetState(){
        $originator = Originator::getInstance();
        $memento = $originator->getMemento($this->id);
        $this->_number = $memento->_number;
        $this->_name = $memento->_name;
        $this->_sumLateMinute = $memento->_sumLateMinute;
    }
}
echo "-------------------张三考勤数据---------------------<br />";
$staffA = new Staff("张三");
$staffA->init();
$staffA->saveState();
$staffA->regLate(10);
$staffA->displayState(); //查看状态
$staffA->regLate(20);
$staffA->displayState(); //查看状态
echo "-------------------李四考勤数据---------------------<br />";
$staffB = new Staff("李四");
$staffB->init();
$staffB->saveState();
$staffB->regLate(50);
$staffB->displayState(); //查看状态
$staffB->regLate(300);
$staffB->displayState(); //查看状态
echo "-------------------重置后的数据---------------------<br />";
//重置张三的考勤数据
$staffA->resetState();
$staffA->displayState(); //查看状态
//重置李四的考勤数据
$staffB->resetState();
$staffB->displayState(); //查看状态